package org.jing.ext.security;

import org.jing.core.lang.JingException;
import org.jing.core.util.StringUtil;

import java.security.SecureRandom;
import java.util.Base64;
import java.util.Random;

/**
 * Description: <br>
 *
 * @author bks <br>
 * @since 2022-04-18 <br>
 */
public class Common {
    private static final Base64.Encoder BASE64_ENCODER = Base64.getEncoder();

    private static final Base64.Decoder BASE64_DECODER = Base64.getDecoder();

    /**
     * Description: 简单的十六进制解密. <br>
     * 依据utf-8编码. <br>
     *
     * @param content 密文 <br>
     * @return 原文 <br>
     */
    public static String encryptX16(String content) {
        return encryptX16(content, "utf-8");
    }

    /**
     * Description: 简单的十六进制加密. <br>
     *
     * @param content 原文 <br>
     * @param charset 字节解析依据字符集 <br>
     * @return 密文 <br>
     */
    public static String encryptX16(String content, String charset) {
        try {
            Random random = new Random();
            byte[] buffer = content.getBytes(charset);
            StringBuilder header = new StringBuilder();
            StringBuilder body = new StringBuilder();
            int len$ = buffer.length, a;
            header.append(len$).append("==");
            for (byte b : buffer) {
                if (b < 0) {
                    a = random.nextInt(128) * 2 + 1;
                    //noinspection lossy-conversions
                    b += 128;
                }
                else {
                    a = random.nextInt(128) * 2;
                }
                header.append(StringUtil.pad(Integer.toHexString(a), StringUtil.PAD_MODEL_LEFT, '0', 2));
                body.append(StringUtil.pad(Integer.toHexString(b), StringUtil.PAD_MODEL_LEFT, '0', 2));
            }
            header.append(body);
            return header.toString();
        }
        catch (JingException e) {
            throw e;
        }
        catch (Throwable t) {
            throw new JingException(t);
        }
    }

    /**
     * Description: 简单的十六进制解密. <br>
     * 依据utf-8编码. <br>
     *
     * @param content 密文 <br>
     * @return 原文 <br>
     */
    public static String decryptX16(String content) {
        return decryptX16(content, "utf-8");
    }

    /**
     * Description: 简单的十六进制解密. <br>
     *
     * @param content 密文 <br>
     * @param charset 字节解析依据字符集 <br>
     * @return 原文 <br>
     */
    public static String decryptX16(String content, String charset) {
        try {
            content = content.toLowerCase();
            if (!content.matches("^\\d+==[0-9a-z]+$")) {
                throw new JingException("Invalid string to be decrypted");
            }
            int length = Integer.parseInt(content.substring(0, content.indexOf("=")));
            if (!content.matches("^" + length + "==[0-9a-z]{" + length * 4 + "}$")) {
                throw new JingException("Invalid string to be decrypted");
            }
            int start = content.lastIndexOf("=") + 1;
            int p;
            byte[] buffer = new byte[length];
            StringBuilder stbr = new StringBuilder();
            for (int i$ = 0; i$ < length; i$++) {
                if (Integer.parseInt(content.substring(p = (start + i$ * 2), p + 2), 16) % 2 == 0) {
                    buffer[i$] = (byte) (Integer.parseInt(content.substring((p = start + length * 2 + i$ * 2), p + 2), 16));
                }
                else {
                    buffer[i$] = (byte) (Integer.parseInt(content.substring((p = start + length * 2 + i$ * 2), p + 2), 16) - 128);
                }
            }
            return new String(buffer, charset);
        }
        catch (JingException e) {
            throw e;
        }
        catch (Throwable t) {
            throw new JingException(t);
        }
    }

    /**
     * Description: 数据脱敏 <br>
     *
     * @param content <br>
     * @return <br>
     */
    @Deprecated
    public static String desensitize(String content) {
        return content.replaceAll("<password>.*?</password>", "");
    }

    /**
     * Description: 将字节数组转换成16进制字符串 <br>
     *
     * @param buffer 字节数组 <br>
     * @return <br>
     */
    public static String parseByte2HexStr(byte[] buffer) {
        StringBuilder sb = new StringBuilder();
        int length = null == buffer ? 0 : buffer.length;
        for (int i$ = 0; i$ < length; i$++) {
            String hex = Integer.toHexString(buffer[i$] & 0xFF);
            if (hex.length() == 1) {
                hex = '0' + hex;
            }
            sb.append(hex);
        }
        return sb.toString();
    }

    /**
     * Description: 将16进制字符串转换为字节数组 <br>
     *
     * @param hexStr 16进制字符串 <br>
     * @return <br>
     */
    public static byte[] parseHexStr2Byte(String hexStr) {
        if (StringUtil.isEmpty(hexStr)) {
            return null;
        }
        int len = hexStr.length();
        if ((len & 1) == 1) {
            hexStr = "0" + hexStr;
            len++;
        }
        int size = len / 2;
        byte[] result = new byte[size];
        for (int i$ = 0; i$ < size; i$++) {
            int high = Integer.parseInt(hexStr.substring(i$ * 2, i$ * 2 + 1), 16);
            int low = Integer.parseInt(hexStr.substring(i$ * 2 + 1, i$ * 2 + 2), 16);
            result[i$] = (byte) (high * 16 + low);
        }
        return result;
    }

    /**
     * Description: 获取复用的Base64编码器 <br>
     *
     * @return <br>
     */
    public static Base64.Encoder getBase64Encoder() {
        return BASE64_ENCODER;
    }

    /**
     * Description: 获取复用的Base64解码器 <br>
     *
     * @return <br>
     */
    public static Base64.Decoder getBase64Decoder() {
        return BASE64_DECODER;
    }

    /**
     * Description: 随机填充字节数组 <br>
     *
     * @param length 字节数组长度 <br>
     * @return <br>
     */
    public static byte[] randomBytes(int length) {
        byte[] ivArr = new byte[length];
        new SecureRandom().nextBytes(ivArr);
        return ivArr;
    }
}
